# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1496.1.1 -> 1.1496.1.2 # arch/ia64/kernel/irq.c 1.31 -> 1.32 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/11/26 davidm@tiger.hpl.hp.com 1.1498 # Drop KERN_CACHEDECAYTICKS sysctl. # Add KERN_GATE_DSO sysctl, which allows to register a pathname for # the file containing an image of the gate DSO. # -------------------------------------------- # 03/12/01 pj@sgi.com 1.1496.1.2 # [PATCH] ia64: fix smp_affinity user-space accesses # # Here is a new improved patch for verifying user access to string # passed in to kernel on write to /proc/irq//smp_affinity. # # The access_ok() but missing __get_user() on each byte earlier patch # has been replaced with a copy_from_user(). # # I have built it and verified that it handles write requests # as before, on an ia64 system (well - you can no longer pass # more than 14 spaces after the 'R' - tough). # -------------------------------------------- # diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Sun Dec 14 00:40:29 2003 +++ b/arch/ia64/kernel/irq.c Sun Dec 14 00:40:29 2003 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -997,21 +998,37 @@ unsigned int irq = (unsigned long) data; int full_count = count, err; cpumask_t new_value, tmp; - const char *buf = buffer; +# define R_PREFIX_LEN 16 + char rbuf[R_PREFIX_LEN]; + int rlen; + int prelen; irq_desc_t *desc = irq_descp(irq); - int redir; if (!desc->handler->set_affinity) return -EIO; - if (buf[0] == 'r' || buf[0] == 'R') { - ++buf; - while (*buf == ' ') ++buf; - redir = 1; - } else - redir = 0; + /* + * If string being written starts with a prefix of 'r' or 'R' + * and some limited number of spaces, set IA64_IRQ_REDIRECTED. + * If more than (R_PREFIX_LEN - 2) spaces are passed, they won't + * all be trimmed as part of prelen, the untrimmed spaces will + * cause the hex parsing to fail, and this write() syscall will + * fail with EINVAL. + */ + + if (!count) + return -EINVAL; + rlen = min(sizeof(rbuf)-1, count); + if (copy_from_user(rbuf, buffer, rlen)) + return -EFAULT; + rbuf[rlen] = 0; + prelen = 0; + if (tolower(*rbuf) == 'r') { + prelen = strspn(rbuf, "Rr "); + irq |= IA64_IRQ_REDIRECTED; + } - err = parse_hex_value(buf, count, &new_value); + err = parse_hex_value(buffer+prelen, count-prelen, &new_value); if (err) return err; @@ -1024,7 +1041,7 @@ if (cpus_empty(tmp)) return -EINVAL; - desc->handler->set_affinity(irq | (redir? IA64_IRQ_REDIRECTED : 0), new_value); + desc->handler->set_affinity(irq, new_value); return full_count; }